local skynet = require "skynet"
require "skynet.manager"
local ServiceName = require "enum.ServiceName"

---@class EventMgr
local M = {}

---@alias address integer
---@alias funcName string
---@alias event string|integer
---@alias true true
---@type table<event, table<number, true>>
local listeners = {}

function M.listen(source, eventName)
    if not listeners[eventName] then
        listeners[eventName] = {}
    end

    listeners[eventName][source] = true
end

function M.listenBatch(source, events)
    for _, event in pairs(events) do
        M.listen(source, event)
    end
end

function M.unlisten(source, eventName)
    if listeners[eventName] then
        listeners[eventName][source] = nil
    end
end

function M.unlistenBatch(source, events)
    for _, event in pairs(events) do
        M.unlisten(source, event)
    end
end

function M.dispatch(_, event, ...)
    for listener in pairs(listeners[event] or {}) do
        skynet.send(listener, "lua", "_receive", event, ...)
    end
end

-- 同步派发事件，可以获取到返回值，其原理是每个监听者返回一个table，然后合并成一个table返回
function M.dispatchSync(_, event, ...)
    local result = {}
    for listener in pairs(listeners[event] or {}) do
        local oneResult = skynet.call(listener, "lua", "_receive", event, ...)
        if oneResult then
            table.insert(result, oneResult)
        end
    end

    local ret = {}
    for i = 1, #result do
        for k, v in pairs(result[i]) do
            ret[k] = v
        end
    end

    return ret
end

function M.init()
    skynet.dispatch_src_lua(M)
    skynet.register(ServiceName.EVENT_MGR)
end

return M
